package cc.wanforme.st.server.base.service.impl;

import cc.wanforme.st.server.base.constant.CacheKeys;
import cc.wanforme.st.server.base.entity.Permission;
import cc.wanforme.st.server.base.mapper.PermissionMapper;
import cc.wanforme.st.server.base.service.IPermissionService;
import cc.wanforme.st.server.base.service.cache.PermissionCacheService;
import cc.wanforme.st.server.exception.MunkRuntimeException;
import cc.wanforme.st.server.util.AssertCheck;
import cc.wanforme.st.server.vo.base.PermissionTreeVo;
import cc.wanforme.st.server.vo.base.PermissionVo;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wanne
 * @since 2022-03-02
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission>
	implements IPermissionService {

	@Autowired
	private PermissionCacheService permissionCacheService;
	
	public Permission saveVo(PermissionVo permission) {
		AssertCheck.nonNull(permission.getCode(), "缺少权限代码");
		permission.setCreateTime(LocalDateTime.now());
		
		Permission po = permission.toPo();
		this.save(po);
		permissionCacheService.clearTree();
		return po;
	}
	
	public void updateVo(PermissionVo permission) {
		AssertCheck.nonNull(permission.getId(), "未选择权限");
		AssertCheck.nonNull(permission.getCode(), "缺少权限代码");
		
		Permission existed = this.getByPermissionCode(permission.getCode());
		if(existed!=null && !Objects.equals(existed.getId(), permission.getId())) {
			throw new MunkRuntimeException("权限代码已存在了！");
		}
		
		Permission po = permission.toPo();
		this.updateById(po);
		permissionCacheService.clearTree();
	}
	
	public void deleteVo(String id) {
		this.baseMapper.deleteById(id);
	}
	
	public PageInfo<PermissionVo> searchPermissions(int page, int pageSize, String permission, String description) {
		PageHelper.startPage(page, pageSize);
		List<Permission> list = this.baseMapper.listPermissions(permission, description);
		PageInfo<Permission> pageInfoPo = new PageInfo<>(list);
		
		PageInfo<PermissionVo> resultPageInfo = new PageInfo<>();
		BeanUtils.copyProperties(pageInfoPo, resultPageInfo, "list");
		
		List<PermissionVo> results = list.stream().map(PermissionVo::new).collect(Collectors.toList());
		for (PermissionVo v : results) {
			if(v.getPid()!=null) {
				Permission parent = this.getById(v.getPid());
				if(parent!=null) {
					v.setPcode(parent.getCode());
				}
			}
		}
		
		resultPageInfo.setList(results);
		return resultPageInfo;
	}

	@Override
	public Permission getByPermissionCode(String code) {
		return this.baseMapper.getByPermissionCode(code);
	}
	
	@Override
	@Cacheable(cacheNames = CacheKeys.PERMISSION_TREE)
	public List<PermissionTreeVo> permissionTree() {
		List<Permission> list = this.list();
		if(list==null || list.isEmpty()) {
			return new ArrayList<>(0);
		}
		
		List<Permission> roots = list.stream()
					.filter(e -> e.getPid()==null)
					.collect(Collectors.toList());
		
		// 不考虑结构混乱的情况
		if(roots.isEmpty()) {
			return new ArrayList<>(0);
		}
		list.removeAll(roots);
		
		List<PermissionTreeVo> rootVo = roots.stream().map(PermissionTreeVo::new).collect(Collectors.toList());
		
//		Queue<PermissionTreeVo> parents = new ArrayBlockingQueue<>(rootVo.size(), false, rootVo);
		Queue<PermissionTreeVo> parents = new LinkedBlockingQueue<>(rootVo);
		// 找到
		while(!parents.isEmpty()) {
			PermissionTreeVo p = parents.poll();
			
			// 筛选子节点
			List<Permission> children = list.stream()
					.filter(e -> Objects.equals(e.getPid(), p.getId()))
					.collect(Collectors.toList());
			
			// 移除
			list.removeAll(children);
			
			// 转换成vo
			List<PermissionTreeVo> childrenVo = children.stream().map(PermissionTreeVo::new)
					.collect(Collectors.toList());
			
			// 设置子节点
			p.setChildren(childrenVo);
			
			// 添加新的根节点
			parents.addAll(childrenVo);
		}
		
		// 但 parents 为空的时候，可能还有部分没有父节点的数据，忽略不处理
		
		return rootVo;
	}
	
}
